package com.hunliji.monitor.share.utils;

import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.statement.*;
import com.alibaba.druid.sql.parser.ParserException;
import com.alibaba.druid.util.JdbcConstants;
import com.hunliji.common.exception.WarnException;
import com.hunliji.monitor.share.enums.db.SqlCheckStatusEnum;
import org.apache.commons.lang3.StringUtils;

import java.util.List;

/**
 * SQL解析工具类
 * @author wuchen
 */
public class SqlParseUtils {
    private final static String MYSQL = "mysql";
    private final static String WHERE = " where ";
    /**
     * 查询数量的语句
     */
    private final static String SELECT_COUNT = "select count(*) from ";
    /**
     * 检查是否可以作为DDL进行sql执行
     * @param sql sql语句
     * @return
     */
    public static Integer checkDDL(String sql) {
        try {
            List<SQLStatement> statements = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
            SQLStatement statement = statements.get(0);
            //插入语句和创建语句则可以执行
            if (statement instanceof SQLCreateStatement || statement instanceof SQLAlterTableStatement) {
                return SqlCheckStatusEnum.EXECUTABLE.getCode();
            }
            return SqlCheckStatusEnum.UNENFORCEABLE.getCode();
        }catch (ParserException e){
            throw new WarnException("sql 解析异常，异常信息,异常信息:"+e.getMessage());
        }
    }

    public static void main(String[] args) {
        String sql = "update aa set bb=1";
        Integer code = checkDDL(sql);
    }

    /**
     * 根据原SQL重组count语句
     * @param sql 原sql
     * @return SQL
     */
    public static String rebuildCountSql(String sql) {
        // 解析
        List<SQLStatement> statements = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
        SQLStatement statement = statements.get(0);

        if (statement instanceof SQLUpdateStatement) {
            SQLUpdateStatement updateStatement = (SQLUpdateStatement) statement;
            return buildCountSql(updateStatement.getTableName().getSimpleName(),
                    updateStatement.getWhere().toString());
        }

        if (statement instanceof SQLAlterTableStatement) {
            SQLAlterTableStatement alterTableStatement = (SQLAlterTableStatement) statement;
            return buildCountSql(alterTableStatement.getTableName(), null);
        }

        return null;
    }

    /**
     * 重构sql 语句，对表做count
     * @param tableName
     * @param where
     * @return
     */
    private static String buildCountSql(String tableName, String where) {
        if (StringUtils.isBlank(tableName)) {
            throw new IllegalArgumentException("SqlParseUtils#buildCountSql: table name are not allowed to be empty.");
        }

        StringBuilder COUNT = new StringBuilder(SELECT_COUNT);
        COUNT.append(tableName);
        if (StringUtils.isNotBlank(where)) {
            COUNT.append(WHERE).append(where);
        }

        return SQLUtils.format(COUNT.toString(), MYSQL);
    }
}
